#include "events/common_log.h"
#include <unistd.h>
#include <stdint.h>
#include <signal.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/tcp.h>
#include <linux/netlink.h>
#include <pthread.h>
#include <termios.h>
#include <dirent.h>
#include <sys/vfs.h>
#include <sys/mman.h>
#include <linux/ioctl.h>
#include <linux/i2c-dev.h>
#include "common_port.h"

CommonPort::CommonPort()
{

}

/**
 * @brief CommonPort::getMMCDeviceName
 * @param name
 * @return
 * @note 获取mmc卡的名字
 */
int CommonPort::getMMCDeviceName(char *name)
{
    struct dirent **namelist;
    const char *dir_path = "/sys/block/mmcblk0/";
    int ret = -1, n;

    n = scandir(dir_path, &namelist, NULL, alphasort);
    if (n < 0)
    {
        GEN_Printf(LOG_ERROR, "scandir not found");
        return ret;
    }

    while(n--)
    {
        if ((namelist[n]->d_type == DT_DIR || namelist[n]->d_type & DT_LNK) &&
            !strncmp(namelist[n]->d_name, "mmcblk", 6))
        {
            sprintf(name, "/dev/%s", namelist[n]->d_name);
            ret = 1;
            break;
        }
        free(namelist[n]);
    }

    free(namelist);
    if (ret != 1)
    {
        strcpy(name, "/dev/mmcblk0");
        ret = 1;
    }

    return ret;
}

/**
 * @brief CommonPort::getAvailDiskSpace
 * @param path
 * @return
 * @note 浏览MMC中可用的存储空间
 */
long CommonPort::getAvailDiskSpace(const char *path)
{
    struct statfs s;
    if(path == NULL)
        return -1;

    if(statfs((char*)path, &s) != 0)
    {
        GEN_Printf(LOG_ERROR, "get space failed !");
        return -1;
    }

    return kscale(s.f_bavail, s.f_bsize);
}

/**
 * @brief CommonPort::getFullDiskSpace
 * @param path
 * @return 浏览MMC存储空间全部大小
 */
long CommonPort::getFullDiskSpace(const char *path)
{
    struct statfs s;
    if(path == NULL)
        return -1;

    if(statfs((char*)path, &s) != 0) {
        return -1;
    }

    return kscale(s.f_blocks, s.f_bsize);
}

long CommonPort::getDiskSpace(const char *path)
{
    struct statfs s;
    if(path == NULL)
        return -1;
    if(statfs((char*)path, &s) != 0) {
        return -1;
    }
    return kscale(s.f_bavail, s.f_bsize);
}

/**
 * @brief CommonPort::getDiskFreeSpace
 * @param [in] lpRootPathName 根目录
 * @param [out] lpSectorsPerCluster 每个集群的扇区
 * @param [out] lpBytesPerSector 每个扇区字节
 * @param [out] lpNumberOfFreeClusters 空闲集群
 * @param [out] lpTotalNumberOfClusters 总集群
 * @return 返回0正确，-1错误
 * @note 获取磁盘空闲空间
 */
int CommonPort::getDiskFreeSpace(const char *lpRootPathName, int *lpSectorsPerCluster, int *lpBytesPerSector, int *lpNumberOfFreeClusters, int *lpTotalNumberOfClusters)
{
    struct statfs statfsbuf;

    if (statfs(lpRootPathName, &statfsbuf))
    {
        GEN_Printf(LOG_ERROR, "statfs %s fail.Error is %s\n", lpRootPathName, strerror(errno));
        return -1;
    }

    if (lpSectorsPerCluster)
    {
        *lpSectorsPerCluster = 1;
    }

    if (lpBytesPerSector)
    {
        *lpBytesPerSector = statfsbuf.f_bsize;
    }

    if (lpNumberOfFreeClusters)
    {
        *lpNumberOfFreeClusters = statfsbuf.f_bfree;
    }

    if (lpTotalNumberOfClusters)
    {
        *lpTotalNumberOfClusters = statfsbuf.f_blocks;
    }
    return 0;
}

long CommonPort::getDirSpace(const char *dir)
{
    long size = 0;
    char cmd[256];

    snprintf(cmd, sizeof(cmd), "du -d 0 %s", dir);

    FILE *file = popen(cmd, "r");
    if (file)
    {
        while (fgets(cmd, sizeof(cmd)-1, file))
        {
            size = strtol(cmd, NULL, 10);
            break;
        }
        pclose(file);
    }
    return size;
}

void CommonPort::printSystemUptime()
{
    char cmd[256];

    FILE *file = popen("uptime", "r");
    if (file)
    {
        while (fgets(cmd, sizeof(cmd)-1, file))
        {
            GEN_Printf(LOG_INFO, "System Load: %s", cmd);
            break;
        }
        pclose(file);
    }
}

/**
 * @brief CommonPort::getCurrentTime_ms
 * @return
 * @note 获取当前时间，毫秒为单位
 */
uint64_t CommonPort::getCurrentTime_ms()
{
    struct timeval tv;
    gettimeofday(&tv,NULL);
    return (uint64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

/**
 * @brief CommonPort::getCurrentTime_us
 * @return
 * @note 获取当前时间，微秒为单位
 */
uint64_t CommonPort::getCurrentTime_us()
{
    struct timeval tv;
    gettimeofday(&tv,NULL);
    return (uint64_t)tv.tv_sec * 1000000ll + tv.tv_usec;
}

uint64_t CommonPort::getCurrentCPUTime_us()
{
    struct timespec now;

    clock_gettime(CLOCK_MONOTONIC, &now);
    return (uint64_t)now.tv_sec * 1000000 + now.tv_nsec/1000;
}

uint64_t CommonPort::getCurrentCPUTime_ms()
{
    struct timespec now;

    clock_gettime(CLOCK_MONOTONIC, &now);
    return (uint64_t)now.tv_sec * 1000 + now.tv_nsec/1000000;
}

uint32_t CommonPort::getCurrentCPUTime_s()
{
    struct timespec now;

    clock_gettime(CLOCK_MONOTONIC, &now);
    return (uint32_t)now.tv_sec;
}

bool CommonPort::s_system(const char *cmd)
{
    pid_t status;
    status = ::system(cmd);
    return (-1 == status || !WIFEXITED(status) || (WIFEXITED(status) && 0!=WEXITSTATUS(status))) ? false : true;
}

bool CommonPort::s_chdir(const char *cmd)
{
    return  0 == ::chdir(cmd) ? true : false;
}

bool CommonPort::s_system_text(const char *ptr, char *buf, const int32_t buf_len, int32_t *len)
{
    if(NULL == ptr || NULL == buf)
        return false;

    FILE* fp = popen(ptr, "r");

    memset(buf, 0, buf_len);
    if(len)
    {
        *len = fread(buf, 1, buf_len, fp);
    } else
    {
        fread(buf, 1, buf_len, fp);
    }

    pclose(fp);

    return true;
}

unsigned int CommonPort::getCrc32(const void *buf, int size)
{
    unsigned int crc=0;
    const unsigned char *p;
    static unsigned int crc32_tab[] = {
       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
       0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
       0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
       0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
       0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
       0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
       0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
       0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
       0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
       0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
       0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
       0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
       0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
       0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
       0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
       0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
       0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
       0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
       0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
       0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
       0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
       0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
       0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
       0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
       0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
       0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
       0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
       0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
       0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
       0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
       0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
       0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
       0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
       0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
       0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
       0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
       0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
       0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
       0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
    };

    p = (unsigned char *)buf;
    crc = crc ^ ~0U;
    while (size--){
        crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
    }
    return crc ^ ~0U;
}

int CommonPort::genSessionToken()
{
    static int current_token = 1;
    if (current_token > 0x7fffffff) {
        current_token = 1;
    }

    return current_token++;
}

unsigned int* __attribute__((weak)) CommonPort::DWLMapRegisters(int mem_dev, unsigned int base, unsigned int regSize, unsigned int write)
{
    const int pageSize = getpagesize();
    const int pageAlignment = pageSize - 1;

    size_t mapSize;
    const char *io = (char *)MAP_FAILED;

    /* increase mapping size with unaligned part */
    mapSize = regSize + (base & pageAlignment);

    /* map page aligned base */
    if(write)
    {
        io = (char *) mmap(0, mapSize, PROT_READ | PROT_WRITE,
                           MAP_SHARED, mem_dev, base & ~pageAlignment);
    } else
    {
        io = (char *) mmap(0, mapSize, PROT_READ, MAP_SHARED,
                           mem_dev, base & ~pageAlignment);
    }

    /* add offset from alignment to the io start address */
    if(io != MAP_FAILED)
    {
        io += (base & pageAlignment);
    } else
    {
        return nullptr;
    }

    return (unsigned int *) io;
}

void __attribute__((weak)) CommonPort::DWLUnmapRegisters(const void *io, unsigned int regSize)
{
    const int pageSize = getpagesize();
    const int pageAlignment = pageSize - 1;

    munmap((void *) ((long) io & (~pageAlignment)),
           regSize + ((long) io & pageAlignment));
}

int CommonPort::recvn(int fd, void *buffer, int n)
{
    ssize_t numRead = 0;
    int totRead = 0;
    int err = 0;
    char *buf;
    buf = (char *)buffer;

    for (totRead = 0; totRead < n; ) {
        numRead = recv(fd, buf, n - totRead, 0);
        err = errno;
        if (numRead == 0)
            return totRead;
        if (numRead == -1) {            
            if (err == EINTR)
            {
                continue;
            } else if(EAGAIN== err)
            {
                return totRead;
            }else {
                return -1;
            }
        }
        totRead += numRead;
        buf += numRead;
    }

    return totRead;
}

int CommonPort::sendn(int fd, const void *buffer, int n)
{
    ssize_t numWritten;
    int totWritten = 0;
    const char *buf;
    buf = (char *)buffer;

    for (totWritten = 0; totWritten < n; ) {
        numWritten = send(fd, buf, n - totWritten, 0);
        if (numWritten <= 0) {
            if (numWritten == -1 && errno == EINTR)
                continue;
            else
                return -1;
        }
        totWritten += numWritten;
        buf += numWritten;
    }
    return totWritten;
}

bool CommonPort::checkSockDead(int sock)
{
    struct tcp_info info;
    int len = sizeof(info);
    getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len);
    if ((info.tcpi_state == TCP_ESTABLISHED))
    {
        return false;
    } else
    {
        return true;
    }
}

int CommonPort::write_all(int fd, const void *buf, size_t count)
{
    while (count)
    {
        ssize_t tmp;

        errno = 0;
        tmp = write(fd, buf, count);
        if (tmp > 0)
        {
            count -= (size_t)tmp;
            if (count)
            {
                buf = (const void *) ((const char *) buf + tmp);
            }
        } else if (errno != EINTR && errno != EAGAIN)
        {
            return -1;
        }
        if (errno == EAGAIN)	/* Try later, *sigh* */
        {
            usleep(250000);
        }
    }
    return 0;
}

int CommonPort::fwrite_all(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
    while (nmemb)
    {
        size_t tmp;

        errno = 0;
        tmp = fwrite(ptr, size, nmemb, stream);

        if (tmp > 0)
        {
            nmemb -= tmp;
            if (nmemb)
            {
                ptr = (const void *) ((const char *) ptr + (tmp * size));
            }
        } else if (errno != EINTR && errno != EAGAIN)
        {
            return -1;
        }

        if (errno == EAGAIN)	/* Try later, *sigh* */
        {
            usleep(250000);
        }
    }
    return 0;
}

ssize_t CommonPort::read_all(int fd, char *buf, size_t count)
{
    ssize_t ret;
    ssize_t c = 0;
    int tries = 0;

    while (count > 0)
    {
        ret = read(fd, buf, count);
        if (ret <= 0)
        {
            if (ret < 0 && (errno == EAGAIN || errno == EINTR) && (tries++ < 5))
            {
                usleep(250000);
                continue;
            }
            return c ? c : -1;
        }
        tries = 0;
        count -= ret;
        buf += ret;
        c += ret;
    }
    return c;
}

int CommonPort::openComPort(int com_port)
{
    char dev[32];
    int fd = -1, ret = -1;

    if (com_port > 4)
        return -1;

    sprintf(dev, "/dev/ttyS%d", com_port);

    fd = open(dev, O_RDWR);//|O_NOCTTY|O_NDELAY
    if (fd < 0) {
        GEN_Printf(LOG_ERROR, "Can't Open Serial Port ttyS%d", com_port);
        return -1;
    }

    if (fcntl(fd, F_SETFL, 0) < 0) {
        GEN_Printf(LOG_ERROR, "fcntl failed!\n");
        goto exit;
    }

        ret = 0;
exit:
    if (ret < 0)
        close(fd);
    return fd;
}

int CommonPort::setComOpt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
    struct termios newtio;

    bzero(&newtio, sizeof(newtio));
    if (tcgetattr(fd, &newtio) != 0) {
        perror("SetupSerial 1");
        return -1;
    }

    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;

    switch(nBits) {
    case 7:
        newtio.c_cflag |= CS7;
        break;
    case 8:
        newtio.c_cflag |= CS8;
        break;
    }

    switch(nEvent) {
    case 'O':
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);
        break;
    case 'E':
        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        break;
    case 'N':
        newtio.c_cflag &= ~PARENB;
        break;
    }

    switch(nSpeed) {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;

    case 4800:
        cfsetispeed(&newtio, B4800);
        cfsetospeed(&newtio, B4800);
        break;

    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;

    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;

    case 460800:
        cfsetispeed(&newtio, B460800);
        cfsetospeed(&newtio, B460800);
        break;

    default:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }

    if (nStop == 1)
        newtio.c_cflag &= ~CSTOPB;
    else if (nStop == 2)
        newtio.c_cflag |= CSTOPB;

    newtio.c_lflag &= ~(ICANON | ISIG | ECHO | IEXTEN);
    newtio.c_iflag &= ~(INPCK|BRKINT|ICRNL|ISTRIP|IXON);
    newtio.c_oflag  &= ~OPOST;

    newtio.c_cc[VTIME] = 1;
    newtio.c_cc[VMIN] = 64;

    tcflush(fd,TCIFLUSH);


    if ((tcsetattr(fd, TCSANOW, &newtio)) != 0) {
        perror("com set error");
        return -1;
    }
    return 0;
}

int CommonPort::openLocalSocket(int port)
{
    int	sock = -1, err = 0;
    struct sockaddr_in sin;
    socklen_t len = (socklen_t) sizeof(sockaddr_in);;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
        return -1;

    memset(&sin, 0, sizeof(sin));
    sin.sin_family		= AF_INET;
    sin.sin_port		= htons(port);
    sin.sin_addr.s_addr	= /*inet_addr(_server_ip); */htonl(INADDR_LOOPBACK);

    err = connect(sock, (struct sockaddr *)&sin, len);
    if (err){
        GEN_Printf(LOG_DEBUG, "Connect error(%d, %s)", errno, strerror(errno));
        goto exit;
    }

exit:
    if (err && sock > 0) {
        close(sock);
        sock = -1;
    }
    return (sock);
}

int CommonPort::sendLocalMessage(int inSock, const void *inMsg, int inLen)
{
    int		err;
    struct sockaddr_in sin;
    socklen_t		len;
    ssize_t			n;

    len = (socklen_t) sizeof( sin );
    err = getsockname( inSock, (struct sockaddr *)&sin, &len );
    if (err)
        goto exit;
    n = sendto( inSock, (char *) inMsg, inLen, 0, (struct sockaddr *)&sin, (socklen_t) sizeof( sin ) );

    if (n != inLen) {
        if (errno == EISCONN) {
            n = send( inSock, (char *) inMsg, inLen, 0 );
        }
    }

exit:
    return(err);
}

int CommonPort::openNetlinkSocket()
{
    struct sockaddr_nl client;
    int socketfd, ret;

    socketfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
    if (socketfd < 0)
        return -1;

    memset(&client, 0, sizeof(client));
    client.nl_family = AF_NETLINK;
    client.nl_pid = getpid();//getpid() + (port_num++);
    client.nl_groups = 1; /* receive broadcast message*/

    ret = bind(socketfd, (struct sockaddr*)&client, sizeof(client));
    if (ret < 0) {
        close(socketfd);
        return -1;
    }
    return socketfd;
}

typedef union
{
    struct sockaddr         sa;
    struct sockaddr_in      v4;
    struct sockaddr_in6     v6;
} sockaddr_ip;

int CommonPort::allocSocket(const char *ip, int port, bool isTcp, bool isIpv4)
{
    int on = 1, err = 0;
    sockaddr_ip sip;
    int         fd;

    fd = socket(isIpv4 ? AF_INET : AF_INET6, isTcp ? SOCK_STREAM : SOCK_DGRAM, isTcp ? IPPROTO_IP : IPPROTO_UDP);
    if (fd == -1)
    {
        GEN_Printf(LOG_ERROR, "socket error, %s\n", strerror(errno));
        return -1;
    }

    if (isIpv4)
    {
        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
        {
            GEN_Printf(LOG_ERROR, "setsockopt(SO_REUSEADDR) failed: %s\n", strerror(errno));
            goto err;
        }

        bzero(&sip.v4, sizeof(sip.v4));
        sip.v4.sin_family = AF_INET;
        sip.v4.sin_port = htons(port);
        if (ip == NULL)
        {
            sip.v4.sin_addr.s_addr = htonl(INADDR_ANY);
        } else {
            sip.v4.sin_addr.s_addr = inet_addr(ip);
        }

        err = bind(fd, (struct sockaddr *)&sip.v4, sizeof(sip.v4));
        if ( err < 0)
        {
            GEN_Printf(LOG_ERROR, "bind err, %s\n", strerror(errno));
            goto err;
        }
    } else
    {
        on = 1;
        err = setsockopt( fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &on, (socklen_t) sizeof( on ) );
        if (err < 0)
        {
            GEN_Printf(LOG_ERROR, "setsockopt(IPV6_V6ONLY) failed: %s\n", strerror(errno));
            goto err;
        }
        memset( &sip.v6, 0, sizeof( sip.v6 ) );

        sip.v6.sin6_family	= AF_INET6;
        sip.v6.sin6_port	= htons( (uint16_t) port );
        sip.v6.sin6_addr	= in6addr_any;
        err = bind( fd, (struct sockaddr *)&sip.v6, (socklen_t) sizeof( sip.v6 ) );
        if ( err < 0)
        {
            GEN_Printf(LOG_ERROR, "ipv6 bind err, %s\n", strerror(errno));
            goto err;
        }
    }

    if (isTcp)
    {
        err = listen(fd, SOMAXCONN);
        if (err < 0)
        {
            err = listen(fd, 5);
            if (err < 0)
            {
                GEN_Printf(LOG_ERROR, "listen error%s\n", strerror(errno));
                goto err;
            }
        }
    }

//    if (1)
//    {
//        len = (socklen_t) sizeof( sip );
//        err = getsockname( fd, &sip.sa, (socklen_t *)&len );
//        if (0 == err)
//        {
//            if( sip.sa.sa_family == AF_INET )
//            {
//                port = ntohs( ( (const struct sockaddr_in  *) &sip.sa )->sin_port );
//            } else if( sip.sa.sa_family == AF_INET6 )
//            {
//                port = ntohs( ( (const struct sockaddr_in6 *) &sip.sa )->sin6_port );
//            } else
//            {
//                GEN_Printf(LOG_WARN, "unknown family: %d", sip.sa.sa_family );
//                port = -1;
//            }
//            // GEN_Printf(LOG_DUMP, "Out Port: %d", port);
//        }
//    }

    return fd;
err:
    if (fd != 0) {
        close(fd);
        fd = -1;
    }

    return -1;
}

#define	kStringToIPAddressFlagsNone				0			//! No flags.
#define	kStringToIPAddressFlagsNoPort			( 1 << 0 )	//! Don't allow a port number to be specified.
#define	kStringToIPAddressFlagsNoPrefix			( 1 << 1 )	//! Don't allow a prefix length to be specified.
#define	kStringToIPAddressFlagsNoScope			( 1 << 2 )	//! Don't allow a scope ID to be specified.
#define	kStringToIPAddressFlagsNoIPv4Mapped		( 1 << 3 )	//! Don't allow IPv4-mapped/compatible IPv6 addresses.
#define	require_action_quiet( X, LABEL, ACTION )														\
    do 																									\
    {																									\
        if( UNLIKELY( !(X) ) ) 																			\
        {																								\
            { ACTION; }																					\
            goto LABEL;																					\
        }																								\
                                                                                                        \
    }	while( 0 )
#define	require_noerr_quiet( ERR, LABEL )																\
    do 																									\
    {																									\
        if( UNLIKELY( (ERR) != 0 ) ) 																	\
        {																								\
            goto LABEL;																					\
        }																								\
                                                                                                        \
    }	while( 0 )

#define	countof( X )						( sizeof( X ) / sizeof( X[ 0 ] ) )
#define	countof_field( TYPE, FIELD )		countof( ( (TYPE *) 0 )->FIELD )

#define kNoErr           0
#define kMalformedErr   -1
#define kRangeErr       -2
#define kUnderrunErr    -3
#define kOverrunErr     -4
#define kUnexpectedErr  -5

static int	parseIPv6Scope( const char *inStr, uint32_t *outScope, const char **outStr )
{
#if 1
    int     			err;
    char				scopeStr[ 64 ];
    char *				dst;
    char *				lim;
    int					c;
    uint32_t			scope;
    const char *		ptr;

    // Copy into a local NULL-terminated string since that is what if_nametoindex expects.

    dst = scopeStr;
    lim = dst + ( countof( scopeStr ) - 1 );
    while( ( ( c = *inStr ) != '\0' ) && ( c != ':' ) && ( c != '/' ) && ( c != ']' ) && ( dst < lim ) )
    {
        *dst++ = *inStr++;
    }
    *dst = '\0';
    SF_ASSERT( dst <= lim );

    // First try to map as a name and if that fails, treat it as a numeric scope.

    scope = if_nametoindex( scopeStr );
    if( scope == 0 )
    {
        for( ptr = scopeStr; ( ( c = *ptr ) >= '0' ) && ( c <= '9' ); ++ptr )
        {
            scope = ( scope * 10 ) + ( c - '0' );
        }
        require_action_quiet( c == '\0', exit, err = kMalformedErr );
        require_action_quiet( ( ptr != scopeStr ) && ( ( (int)( ptr - scopeStr ) ) <= 10 ), exit, err = kMalformedErr );
    }

    *outScope = scope;
    *outStr   = inStr;
    err = kNoErr;

exit:
    return( err );
#else
    OSStatus			err;
    uint32_t			scope;
    const char *		start;
    int					c;

    scope = 0;
    for( start = inStr; ( ( c = *inStr ) >= '0' ) && ( c <= '9' ); ++inStr )
    {
        scope = ( scope * 10 ) + ( c - '0' );
    }
    require_action_quiet( ( inStr != start ) && ( ( (int)( inStr - start ) ) <= 10 ), exit, err = kMalformedErr );

    *outScope = scope;
    *outStr   = inStr;
    err = kNoErr;

exit:
    return( err );
#endif
}

//	Warning: "inBuffer" may be modified even in error cases.
static int	parseIPv4Address( const char *inStr, uint8_t inBuffer[ 4 ], const char **outStr )
{
    int     		err;
    uint8_t *		dst;
    int				segments;
    int				sawDigit;
    int				c;
    int				v;

    SF_ASSERT( inBuffer );
    SF_ASSERT( outStr );

    dst		 = inBuffer;
    *dst	 = 0;
    sawDigit = 0;
    segments = 0;
    for( ; ( c = *inStr ) != '\0'; ++inStr )
    {
        if( isdigit( c ) )
        {
            v = ( *dst * 10 ) + ( c - '0' );
            require_action_quiet( v <= 255, exit, err = kRangeErr );
            *dst = (uint8_t) v;
            if( !sawDigit )
            {
                ++segments;
                require_action_quiet( segments <= 4, exit, err = kOverrunErr );
                sawDigit = 1;
            }
        }
        else if( ( c == '.' ) && sawDigit )
        {
            require_action_quiet( segments < 4, exit, err = kMalformedErr );
            *++dst = 0;
            sawDigit = 0;
        }
        else
        {
            break;
        }
    }
    require_action_quiet( segments == 4, exit, err = kUnderrunErr );

    *outStr = inStr;
    err = kNoErr;

exit:
    return( err );
}

static int	parseIPv6Address( const char *inStr, int inAllowV4Mapped, uint8_t inBuffer[ 16 ], const char **outStr )
{
    // Table to map uppercase hex characters - '0' to their numeric values.
    // 0  1  2  3  4  5  6  7  8  9  :  ;  <  =  >  ?  @  A   B   C   D   E   F
    static const uint8_t		kASCIItoHexTable[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15 };
    int                         err;
    const char *				ptr;
    uint8_t *					dst;
    uint8_t *					lim;
    uint8_t *					colonPtr;
    int							c;
    int							sawDigit;
    unsigned int				v;
    int							i;
    int							n;

    // Pre-zero the address to simplify handling of compressed addresses (e.g. "::1").

    for( i = 0; i < 16; ++i ) inBuffer[ i ] = 0;

    // Special case leading :: (e.g. "::1") to simplify processing later.

    if( *inStr == ':' )
    {
        ++inStr;
        require_action_quiet( *inStr == ':', exit, err = kMalformedErr );
    }

    // Parse the address.

    ptr		 = inStr;
    dst		 = inBuffer;
    lim		 = dst + 16;
    colonPtr = NULL;
    sawDigit = 0;
    v		 = 0;
    while( ( ( c = *inStr++ ) != '\0' ) && ( c != '%' ) && ( c != '/' ) && ( c != ']' ) )
    {
        if(   ( c >= 'a' ) && ( c <= 'f' ) ) c -= ( 'a' - 'A' );
        if( ( ( c >= '0' ) && ( c <= '9' ) ) || ( ( c >= 'A' ) && ( c <= 'F' ) ) )
        {
            c -= '0';
            SF_ASSERT( c < (int) countof( kASCIItoHexTable ) );
            v = ( v << 4 ) | kASCIItoHexTable[ c ];
            require_action_quiet( v <= 0xFFFF, exit, err = kRangeErr );
            sawDigit = 1;
            continue;
        }
        if( c == ':' )
        {
            ptr = inStr;
            if( !sawDigit )
            {
                require_action_quiet( !colonPtr, exit, err = kMalformedErr );
                colonPtr = dst;
                continue;
            }
            require_action_quiet( *inStr != '\0', exit, err = kUnderrunErr );
            require_action_quiet( ( dst + 2 ) <= lim, exit, err = kOverrunErr );
            *dst++ = (uint8_t)( ( v >> 8 ) & 0xFF );
            *dst++ = (uint8_t)(   v        & 0xFF );
            sawDigit = 0;
            v = 0;
            continue;
        }

        // Handle IPv4-mapped/compatible addresses (e.g. ::FFFF:1.2.3.4).

        if( inAllowV4Mapped && ( c == '.' ) && ( ( dst + 4 ) <= lim ) )
        {
            err = parseIPv4Address( ptr, dst, &inStr );
            require_noerr_quiet( err, exit );
            dst += 4;
            sawDigit = 0;
            ++inStr; // Increment because the code below expects the end to be at "inStr - 1".
        }
        break;
    }
    if( sawDigit )
    {
        require_action_quiet( ( dst + 2 ) <= lim, exit, err = kOverrunErr );
        *dst++ = (uint8_t)( ( v >> 8 ) & 0xFF );
        *dst++ = (uint8_t)(   v        & 0xFF );
    }
    SF_ASSERT( dst <= lim );
    if( colonPtr )
    {
        require_action_quiet( dst < lim, exit, err = kOverrunErr );
        n = (int)( dst - colonPtr );
        for( i = 1; i <= n; ++i )
        {
            lim[ -i ] = colonPtr[ n - i ];
            colonPtr[ n - i ] = 0;
        }
        dst = lim;
    }
    require_action_quiet( dst == lim, exit, err = kUnderrunErr );

    *outStr = inStr - 1;
    err = kNoErr;

exit:
    return( err );
}

static int  stringToIPv6Address(const char *inStr, int inFlags, uint8_t outIPv6[16], uint32_t *outScope, int *outPort, int *outPrefix, const char **outStr )
{
    int     		err;
    uint8_t			ipv6[ 16 ];
    int				c;
    int				hasScope;
    uint32_t		scope;
    int				hasPort;
    int				port;
    int				hasPrefix;
    int				prefix;
    int				hasBracket;
    int				i;

    SF_ASSERT(inStr);

    if( *inStr == '[' ) ++inStr; // Skip a leading bracket for []-wrapped addresses (e.g. "[::1]:80").

    // Parse the address-only part of the address (e.g. "1::1").

    err = parseIPv6Address( inStr, !( inFlags & kStringToIPAddressFlagsNoIPv4Mapped ), ipv6, &inStr );
    SF_ASSERT(0 == err);
    c = *inStr;

    // Parse the scope, port, or prefix length.

    hasScope	= 0;
    scope		= 0;
    hasPort		= 0;
    port		= 0;
    hasPrefix	= 0;
    prefix		= 0;
    hasBracket	= 0;
    for( ;; )
    {
        if( c == '%' )		// Scope (e.g. "%en0" or "%5")
        {
            require_action_quiet( !hasScope, exit, err = kMalformedErr );
            require_action_quiet( !( inFlags & kStringToIPAddressFlagsNoScope ), exit, err = kUnexpectedErr );
            ++inStr;
            err = parseIPv6Scope( inStr, &scope, &inStr );
            require_noerr_quiet( err, exit );
            hasScope = 1;
            c = *inStr;
        }
        else if( c == ':' )	// Port (e.g. ":80")
        {
            require_action_quiet( !hasPort, exit, err = kMalformedErr );
            require_action_quiet( !( inFlags & kStringToIPAddressFlagsNoPort ), exit, err = kUnexpectedErr );
            while( ( ( c = *( ++inStr ) ) != '\0' ) && ( ( c >= '0' ) && ( c <= '9' ) ) ) port = ( port * 10 ) + ( c - '0' );
            require_action_quiet( port <= 65535, exit, err = kRangeErr );
            hasPort = 1;
        }
        else if( c == '/' )	// Prefix Length (e.g. "/64")
        {
            require_action_quiet( !hasPrefix, exit, err = kMalformedErr );
            require_action_quiet( !( inFlags & kStringToIPAddressFlagsNoPrefix ), exit, err = kUnexpectedErr );
            while( ( ( c = *( ++inStr ) ) != '\0' ) && ( ( c >= '0' ) && ( c <= '9' ) ) ) prefix = ( prefix * 10 ) + ( c - '0' );
            require_action_quiet( ( prefix >= 0 ) && ( prefix <= 128 ), exit, err = kRangeErr );
            hasPrefix = 1;
        }
        else if( c == ']' )
        {
            require_action_quiet( !hasBracket, exit, err = kMalformedErr );
            hasBracket = 1;
            c = *( ++inStr );
        }
        else
        {
            break;
        }
    }

    // Return the results. Only fill in scope/port/prefix results if the info was found to allow for defaults.

    if( outIPv6 )				 for( i = 0; i < 16; ++i ) outIPv6[ i ] = ipv6[ i ];
    if( outScope  && hasScope )  *outScope	= scope;
    if( outPort   && hasPort )   *outPort	= port;
    if( outPrefix && hasPrefix ) *outPrefix	= prefix;
    if( outStr )				 *outStr	= inStr;
    err = kNoErr;

exit:
    return( err );
}

int CommonPort::allocClientSocket(const char *ip, int port, bool isTcp, bool isIpv4)
{
    sockaddr_ip sip;

    return allocClientSocket(&sip, ip, port, isTcp, isIpv4);
}

int CommonPort::allocClientSocket(void *ipAddr, const char *ip, int port, bool isTcp, bool isIpv4)
{
    int	sock = -1, err = 0;

    sockaddr_ip &sip= *((sockaddr_ip *)ipAddr);
    socklen_t   len = (socklen_t) sizeof(sip);

    sock = socket(isIpv4 ? AF_INET : AF_INET6, isTcp ? SOCK_STREAM : SOCK_DGRAM, isTcp ? IPPROTO_IP : IPPROTO_UDP);
    if (sock < 0)
    {
        GEN_Printf(LOG_ERROR, "socket error, %s\n", strerror(errno));
        return -1;
    }

    if (isIpv4)
    {
        memset(&sip.v4, 0, sizeof(sip.v4));
        sip.v4.sin_family   = AF_INET;
        if (ip)
        {
            const char *addr = strchr(ip, ':');
            if (addr)
            {
                char tmp[32] = {0};
                strncpy(tmp, ip, addr - ip);
                addr++;
                int t = atoi(addr);
                if (t > 0)
                {
                    GEN_Printf(LOG_INFO, "IP Port old[%d] -> new[%d]", port, t);
                    port = t;
                }
                sip.v4.sin_addr.s_addr = inet_addr(tmp);
            } else
            {
                sip.v4.sin_addr.s_addr = inet_addr(ip);
            }
        } else
        {
            sip.v4.sin_addr.s_addr	= htonl(INADDR_LOOPBACK); /*inet_addr(_server_ip); */
        }
        sip.v4.sin_port     = htons(port);
    } else
    {
        uint8_t						ipv6[ 16 ];
        uint32_t					scope = 0;

        memset(&sip.v6, 0, sizeof(sip.v6));
        sip.v6.sin6_family 	= AF_INET6;

        if (ip)
        {
            err = stringToIPv6Address( ip, kStringToIPAddressFlagsNone, ipv6, &scope, &port, NULL, NULL );
            if (err)
            {
                GEN_Printf(LOG_DEBUG, "stringToIPv6Address failed. err=%d", err);
                goto exit;
            }
            sip.v6.sin6_port		= htons( (uint16_t) port );
            memcpy( sip.v6.sin6_addr.s6_addr, ipv6, 16 );
            sip.v6.sin6_scope_id	= scope;
        } else
        {
            sip.v6.sin6_port	= htons( (uint16_t) port );
            sip.v6.sin6_addr	= in6addr_any;
        }
    }

    if (isTcp)
    {
        err = connect(sock, (struct sockaddr *)&sip.sa, len);
        if (err)
        {
            GEN_Printf(LOG_DEBUG, "Connect port=%d error, %s", port, strerror(errno));
            goto exit;
        }
    }

exit:
    if (err && sock > 0) {
        close(sock);
        sock = -1;
    }
    return (sock);
}

int CommonPort::allocLocalSocket(const char *sockfile, bool isHost)
{
    struct sockaddr_un addr;

    int sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
        GEN_Printf(LOG_ERROR, "Create socket[%s] error, %s", sockfile, strerror(errno));
        return -1;
    }

    memset(&addr, 0, sizeof(struct sockaddr_un));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, sockfile, sizeof(addr.sun_path) -1);

    if(isHost)
    {
        // GEN_Printf(LOG_DEBUG, "Bind Socket: %d", sockfd);
        if (-1 == ::bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)))
        {
            GEN_Printf(LOG_ERROR, "Bind[%s] socket failed:%s.", sockfile, strerror(errno));
            close(sockfd);
            return -1;
        }
    }else
    {
        //GEN_Printf(LOG_DEBUG, "Connect Socket: %d", sockfd);
        if(-1 == connect(sockfd,(struct sockaddr*)&addr,sizeof(addr)))
        {
            GEN_Printf(LOG_ERROR, "Connect[%s] socket failed:%s.", sockfile, strerror(errno));
            close(sockfd);
            return -1;
        }
//         int flags = fcntl(sockfd, F_GETFD);
//         flags |= O_NDELAY | MSG_DONTWAIT;
//         fcntl(sockfd, F_SETFD, flags);

//        int on = 1;
//        setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on));
    }
    return sockfd;
}

int CommonPort::allocSyslogLocalSocket(bool isHost)
{
    int  sockfd = -1;
    const char *sockfile = "/tmp/ipcSock/logout.logManager";
    if (0 != access("/tmp/ipcSock", F_OK))
    {
        mkdir("/tmp/ipcSock", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
    }

    struct sockaddr_un sunx;

    memset(&sunx, 0, sizeof(sunx));
    sunx.sun_family = AF_UNIX;
    strcpy(sunx.sun_path, sockfile);

    sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
         GEN_Printf(LOG_ERROR, "create socket failed, %s", strerror(errno));
         return -1;
    }

    if (isHost)
    {
        unlink(sunx.sun_path);

        if (bind(sockfd, (struct sockaddr *) &sunx, sizeof(sunx)))
        {
            GEN_Printf(LOG_ERROR, "%s bind failed, %s", sockfile, strerror(errno));
            unlink(sunx.sun_path);
            close(sockfd);
            return -1;
        } else
        {
            chmod(sockfile, 0666);
        }
    } else
    {
        if(-1 == connect(sockfd, (struct sockaddr*)&sunx, sizeof(sunx)))
        {
            GEN_Printf(LOG_ERROR, "Connect[%s] socket failed:%s.", sockfile, strerror(errno));
            close(sockfd);
            return -1;
        }
    }

    return sockfd;
}

int CommonPort::isExistIp(int fd)
{
    struct ifreq ifr;

    memset(&ifr, 0, sizeof(ifr));

    ifr.ifr_addr.sa_family = AF_INET;
    strcpy(ifr.ifr_name, "wlan0");
    if (ioctl(fd, SIOCGIFADDR, &ifr) != 0)
    {
        //GEN_Printf(LOG_WARN, "ioctl error: %d, %s", fd, strerror(errno));
        return -1;
    }else
    {
        struct sockaddr_in *our_ip = (struct sockaddr_in *) &ifr.ifr_addr;
        GEN_Printf(LOG_INFO, "IP %s", inet_ntoa(our_ip->sin_addr));
    }

    return 0;
}

#define MAC_SPILT "%02X%02X%02X%02X%02X%02X"
//#define MAC_SPILT "%02X:%02X:%02X:%02X:%02X:%02X"
void CommonPort::str2Mac(char mac[13], unsigned char dig[6])
{
    unsigned int  a,b,c,d,e,f;

    sscanf(mac, MAC_SPILT, &a, &b, &c, &d, &e, &f);

    dig[0] = a & 0xFF;
    dig[1] = b & 0xFF;
    dig[2] = c & 0xFF;
    dig[3] = d & 0xFF;
    dig[4] = e & 0xFF;
    dig[5] = f & 0xFF;
}

void CommonPort::mac2Str(unsigned char dig[6], char mac[20])
{
    sprintf(mac, MAC_SPILT, dig[0], dig[1], dig[2], dig[3], dig[4], dig[5]);
}

char *CommonPort::getIpAddress(const char *iface)
{
    struct ifreq ifr;

    int fd = socket(AF_INET, SOCK_STREAM, 0);

    if (fd == -1)
    {
        GEN_Printf(LOG_ERROR, "socket error, %s\n", strerror(errno));
        return NULL;
    }

    memset(&ifr, 0, sizeof(ifr));

    ifr.ifr_addr.sa_family = AF_INET;
    strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)-1);

    if (ioctl(fd, SIOCGIFADDR, &ifr) != 0)
    {
        GEN_Printf(LOG_WARN, "ioctl error: %d, %s", fd, strerror(errno));
        close(fd);
        return NULL;
    }
    close(fd);

    return inet_ntoa(reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_addr)->sin_addr);
}

int CommonPort::allocUDPServiceSocket(const char *ip, int port)
{
    struct sockaddr_in server_addr;
    int fd = socket(AF_INET, SOCK_DGRAM, 0);

    if (fd == -1)
    {
        GEN_Printf(LOG_ERROR, "socket error, %s\n", strerror(errno));
        return -1;
    }

    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    if (ip == NULL)
    {
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    } else
    {
        server_addr.sin_addr.s_addr = inet_addr(ip);
    }

    if (bind(fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
    {
        GEN_Printf(LOG_ERROR, "bind err port: %d, %s\n", port, strerror(errno));
        goto err;
    }

    return fd;
err:
    if (fd != 0) {
        close(fd);
        fd = -1;
    }

    return -1;
}

int CommonPort::allocUDPClientSocket(const char *ip, int port)
{
    int	sock = -1, err = 0;
    struct sockaddr_in sin;
    socklen_t len = (socklen_t) sizeof(sockaddr_in);;

    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        GEN_Printf(LOG_ERROR, "socket failed !!!, %s", strerror(errno));
        return -1;
    }

    memset(&sin, 0, sizeof(sin));
    sin.sin_family		= AF_INET;
    sin.sin_port		= htons(port);
    if (ip)
    {
        sin.sin_addr.s_addr	= inet_addr(ip);
    } else
    {
        sin.sin_addr.s_addr	= htonl(INADDR_LOOPBACK);
    }

    err = connect(sock, (struct sockaddr *)&sin, len);
    if (err){
        GEN_Printf(LOG_DEBUG, "Connect port: %d error(%d, %s)", port, errno, strerror(errno));
        goto exit;
    }

exit:
    if (err && sock > 0) {
        close(sock);
        sock = -1;
    }
    return (sock);
}

bool CommonPort::havaNetInterface(const char *name)
{
    int fd;
    struct ifreq ifr;

    memset(&ifr, 0, sizeof(ifr));
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(fd < 0)
    {
        perror("socket");
        GEN_Printf(LOG_ERROR, "socket fd is error.");
        return false;
    }

    ifr.ifr_addr.sa_family = AF_INET;
    strcpy(ifr.ifr_name, name);

    if (ioctl(fd, SIOCGIFINDEX, &ifr) != 0)
    {
        close(fd);
        perror("ioctl");
        GEN_Printf(LOG_ERROR, "ioctl error: %d.", errno);
        return false;
    }
    GEN_Printf(LOG_INFO, "Adapter index %d", ifr.ifr_ifindex);

    close(fd);
    return true;
}

